#include <iostream>
#include "singleton.h"

class TestSingleton
{
   public:
    TestSingleton() = default;
    ~TestSingleton() = default;
    void testFunc()
    {
        std::cout << "test function -"
                  << "\n";
    }
};

class TestSingleton0
{
   public:
    TestSingleton0()
    {
        std::cout << "lvalue" << std::endl;
    }

    ~TestSingleton0() = default;
    void testFunc()
    {
        std::cout << "test function 0"
                  << "\n";
    }
};

class TestSingleton1
{
   public:
    TestSingleton1(const std::string &)
    {
        std::cout << "lvalue" << std::endl;
    }
    TestSingleton1(std::string &&)
    {
        std::cout << "rvalue" << std::endl;
    }
    ~TestSingleton1() = default;
    void testFunc()
    {
        std::cout << "test function 1"
                  << "\n";
    }
};

class TestSingleton2
{
   public:
    TestSingleton2(const std::string &)
    {
        std::cout << "lvalue" << std::endl;
    }
    TestSingleton2(std::string &&)
    {
        std::cout << "rvalue" << std::endl;
    }
    ~TestSingleton2() = default;
    void testFunc()
    {
        std::cout << "test function 2"
                  << "\n";
    }
};
class TestSingleton3
{
   public:
    TestSingleton3(const std::string &, int i, double k)
    {
        std::cout << "lvalue" << std::endl;
    }
    ~TestSingleton3() = default;
    void testFunc()
    {
        std::cout << "test function 3"
                  << "\n";
    }
};

int main(int argc, char **argv)
{
    std::string str = "bb";
    // std::unique_ptr<TestSingleton> p = Singleton<TestSingleton>::Instance();
    // p->testFunc();
    auto p = Singleton<TestSingleton>::Init();
    p->testFunc();

    Singleton<TestSingleton0>::Getinstance()->testFunc();
    Singleton<TestSingleton0>::Getinstance()->testFunc();
    Singleton<TestSingleton0>::Getinstance()->testFunc();
    Singleton<TestSingleton0>::Getinstance()->testFunc();

    auto p1 = Singleton<TestSingleton1>::Init(str);
    std::cout << " p1 --- " << p1.use_count() << std::endl;

    p1->testFunc();
    std::cout << " p1 --- " << p1.use_count() << std::endl;

    auto p2 = p1;
    std::cout << " p1 --- " << p1.use_count() << std::endl;

    auto p3 = p1;
    std::cout << " p1 --- " << p1.use_count() << std::endl;

    Singleton<TestSingleton1>::Get()->testFunc();

    Singleton<TestSingleton2>::Getinstance(std::move(std::string("xxxx")))->testFunc();
    Singleton<TestSingleton3>::Getinstance("yyyy", 1, 2.0)->testFunc();

    // while (1)
    //     ;
    // return 0;
}
